package org.jeecg.modules.system.controller;


import java.util.HashMap;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.io.IOUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import cn.hutool.crypto.SecureUtil;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.*;
import org.jeecg.common.util.filter.FileTypeFilter;
import org.jeecg.modules.nikeProject.entity.AreaCity;
import org.jeecg.modules.nikeProject.entity.AreaProvince;
import org.jeecg.modules.system.service.IAreaProvinceService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;

/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @Author scott
 * @since 2018-12-20
 */
@Slf4j
//@Api(tags="106公共方法")
@RestController
@RequestMapping("/sys/common")
public class CommonController {

    @Autowired
    private IAreaProvinceService areaProvinceService;

    private final RedisUtil redisUtil;
    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;

    /**
     * 本地：local minio：minio 阿里：alioss
     */
    @Value(value="${jeecg.uploadType}")
    private String uploadType;

    public CommonController(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    /**
     * @Author 政辉
     * @return
     */
    @GetMapping("/403")
    public Result<?> noauth()  {
        return Result.error("没有权限，请联系管理员授权");
    }

    /**
     * 文件上传统一方法,目前用户后台pc端上传
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value="后台文件上传", notes="也可以上传图片，参数：MultipartFile")
    @PostMapping(value = "/upload")
    public Result<?> upload(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Result<?> result = new Result<>();
        String savePath = "";
        String bizPath = request.getParameter("biz");

        //LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
        if (oConvertUtils.isNotEmpty(bizPath)) {
            if(bizPath.contains(SymbolConstant.SPOT_SINGLE_SLASH) || bizPath.contains(SymbolConstant.SPOT_DOUBLE_BACKSLASH)){
                throw new JeecgBootException("上传目录bizPath，格式非法！");
            }
        }

        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        // 获取上传文件对象
        MultipartFile file = multipartRequest.getFile("file");
        if(oConvertUtils.isEmpty(bizPath)){
            if(CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)){
                //未指定目录，则用阿里云默认目录 upload
                bizPath = "upload";
                //result.setMessage("使用阿里云文件上传时，必须添加目录！");
                //result.setSuccess(false);
                //return result;
            }else{
                bizPath = "";
            }
        }
        if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
            //update-begin-author:liusq date:20221102 for: 过滤上传文件类型
            FileTypeFilter.fileTypeFilter(file);
            //update-end-author:liusq date:20221102 for: 过滤上传文件类型
            //update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
            savePath = this.uploadLocal(file,bizPath);
            //update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
            /**  富文本编辑器及markdown本地上传时，采用返回链接方式
            //针对jeditor编辑器如何使 lcaol模式，采用 base64格式存储
            String jeditor = request.getParameter("jeditor");
            if(oConvertUtils.isNotEmpty(jeditor)){
                result.setMessage(CommonConstant.UPLOAD_TYPE_LOCAL);
                result.setSuccess(true);
                return result;
            }else{
                savePath = this.uploadLocal(file,bizPath);
            }
            */
        }else{
            //update-begin-author:taoyan date:20200814 for:文件上传改造
            savePath = CommonUtils.upload(file, bizPath, uploadType);
            //update-end-author:taoyan date:20200814 for:文件上传改造
        }
        if(oConvertUtils.isNotEmpty(savePath)){
            result.setMessage(savePath);
            result.setSuccess(true);
        }else {
            result.setMessage("上传失败！");
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 本地文件上传
     * @param mf 文件
     * @param bizPath  自定义路径
     * @return
     */
    private String uploadLocal(MultipartFile mf,String bizPath){
        try {
            String ctxPath = uploadpath;
            String fileName = null;
            File file = new File(ctxPath + File.separator + bizPath + File.separator );
            if (!file.exists()) {
                // 创建文件根目录
                file.mkdirs();
            }
            // 获取文件名
            String orgName = mf.getOriginalFilename();
            orgName = CommonUtils.getFileName(orgName);
            if(orgName.indexOf(SymbolConstant.SPOT)!=-1){
                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
            }else{
                fileName = orgName+ "_" + System.currentTimeMillis();
            }
            String savePath = file.getPath() + File.separator + fileName;
            File savefile = new File(savePath);
            FileCopyUtils.copy(mf.getBytes(), savefile);
            String dbpath = null;
            if(oConvertUtils.isNotEmpty(bizPath)){
                dbpath = bizPath + File.separator + fileName;
            }else{
                dbpath = fileName;
            }
            if (dbpath.contains(SymbolConstant.DOUBLE_BACKSLASH)) {
                dbpath = dbpath.replace(SymbolConstant.DOUBLE_BACKSLASH, SymbolConstant.SINGLE_SLASH);
            }
            return dbpath;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }

//	@PostMapping(value = "/upload2")
//	public Result<?> upload2(HttpServletRequest request, HttpServletResponse response) {
//		Result<?> result = new Result<>();
//		try {
//			String ctxPath = uploadpath;
//			String fileName = null;
//			String bizPath = "files";
//			String tempBizPath = request.getParameter("biz");
//			if(oConvertUtils.isNotEmpty(tempBizPath)){
//				bizPath = tempBizPath;
//			}
//			String nowday = new SimpleDateFormat("yyyyMMdd").format(new Date());
//			File file = new File(ctxPath + File.separator + bizPath + File.separator + nowday);
//			if (!file.exists()) {
//				file.mkdirs();// 创建文件根目录
//			}
//			MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
//			MultipartFile mf = multipartRequest.getFile("file");// 获取上传文件对象
//			String orgName = mf.getOriginalFilename();// 获取文件名
//			fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));
//			String savePath = file.getPath() + File.separator + fileName;
//			File savefile = new File(savePath);
//			FileCopyUtils.copy(mf.getBytes(), savefile);
//			String dbpath = bizPath + File.separator + nowday + File.separator + fileName;
//			if (dbpath.contains("\\")) {
//				dbpath = dbpath.replace("\\", "/");
//			}
//			result.setMessage(dbpath);
//			result.setSuccess(true);
//		} catch (IOException e) {
//			result.setSuccess(false);
//			result.setMessage(e.getMessage());
//			log.error(e.getMessage(), e);
//		}
//		return result;
//	}

    /**
     * 预览图片&下载文件
     * 请求地址：http://localhost:8080/common/static/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
     *
     * @param request
     * @param response
     */
    @ApiOperation(value ="图片浏览",notes="http://106.14.61.190:7995/voc/sys/common/static/{20230131/imagename_1675143983160.jpg}")
    @GetMapping(value = "/statice/**")
    public void view(HttpServletRequest request, HttpServletResponse response) {
        // ISO-8859-1 ==> UTF-8 进行编码转换
        String imgPath = extractPathFromPattern(request);
        if(oConvertUtils.isEmpty(imgPath) || CommonConstant.STRING_NULL.equals(imgPath)){
            return;
        }
        // 其余处理略
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            imgPath = imgPath.replace("..", "").replace("../","");
            if (imgPath.endsWith(SymbolConstant.COMMA)) {
                imgPath = imgPath.substring(0, imgPath.length() - 1);
            }
            String filePath = uploadpath + File.separator + imgPath;
            File file = new File(filePath);
            if(!file.exists()){
                response.setStatus(404);
                //throw new RuntimeException("文件["+imgPath+"]不存在..");
                log.error("文件["+imgPath+"]不存在..");
            }else {
                // 设置强制下载不打开
                response.setContentType("application/force-download");
                response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"), "iso-8859-1"));
                inputStream = new BufferedInputStream(new FileInputStream(filePath));
                outputStream = response.getOutputStream();
                byte[] buf = new byte[1024];
                int len;
                while ((len = inputStream.read(buf)) > 0) {
                    outputStream.write(buf, 0, len);
                }
                response.flushBuffer();
            }
        } catch (IOException e) {
            log.error("预览文件失败" + e.getMessage());
            response.setStatus(404);
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }

    }


    @ApiOperation(value="产品组件查询", notes="产品组件查询")
    @GetMapping (value = "/prodQuery")
    public Result<JSONObject> prodQuery(@RequestParam(name="moduleId") String moduleId,
                                        HttpServletRequest request, HttpServletResponse response) {

        String url ="https://www.ronmasolar.cn/RMAPI/SalesApp/";

        Result<JSONObject> result = new Result<>();
        JSONObject queryObject= new JSONObject();
        //moduleId = "RM1222080102020";
        String yyMMddHH = DateUtils.formatDate("yyMMddHH");
        String salt = "SDRM1227";
        String temp = SecureUtil.md5(moduleId+yyMMddHH+salt);
        String token=SecureUtil.md5(StringUtils.upperCase(temp));

        HashMap<String, Object> map = new HashMap<>();
        map.put("module_id", moduleId);
        map.put("token", token);
        queryObject.put("module_id", moduleId);
        queryObject.put("token", StringUtils.upperCase(token));
        log.info(queryObject.toString());
        //ResponseEntity res = RestUtil.getNative(url,queryObject, null);
        String res = RestUtil.request(url,queryObject,map);
        log.info(res.toString());
        try {
            JSONObject jsonResult = new JSONObject();
            JSONObject jsonObject = JSONObject.parseObject(res);
            log.info(jsonObject.toJSONString());
            String msg = jsonObject.getString("Msg");
            if(msg.equals("OK")){
                JSONArray jsonArrays = jsonObject.getJSONArray("Info");
                if(jsonArrays!= null && jsonArrays.size()>0){
                    JSONObject jsonObj = jsonArrays.getJSONObject(0);
                    String module_id = jsonObj.getString("module_id");
                    String POWER = jsonObj.getString("POWER");
                    String ipm = jsonObj.getString("ipm");
                    String man_date = jsonObj.getString("man_date");
                    man_date=StringUtils.substringAfter(man_date,"Date(");
                    man_date=StringUtils.substringBefore(man_date,")");
                    man_date = DateUtils.timeConvertStamp(man_date);
                    String pro_date = jsonObj.getString("pro_date");
                    pro_date=StringUtils.substringAfter(pro_date,"Date(");
                    pro_date=StringUtils.substringBefore(pro_date,")");
                    pro_date = DateUtils.timeConvertStamp(pro_date);
                    String product_due_time = jsonObj.getString("product_due_time");
                    String power_due_time = jsonObj.getString("power_due_time");
                    jsonResult.put("module_id",module_id);
                    jsonResult.put("POWER",POWER);
                    jsonResult.put("ipm",ipm);
                    jsonResult.put("man_date",man_date);
                    jsonResult.put("pro_date",pro_date);
                    jsonResult.put("product_due_time",product_due_time);
                    jsonResult.put("power_due_time",power_due_time);
                    return Result.OK(jsonResult);
                }
            }else if(msg.equals("ERROR")&& jsonObject.getString("Info").equals("404")){
                return Result.error("未找到产品信息");
            }else{
                String Info = jsonObject.getString("Info");
                return Result.error(Info);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return Result.error(res.toString());
    }



//	/**
//	 * 下载文件
//	 * 请求地址：http://localhost:8080/common/download/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
//	 *
//	 * @param request
//	 * @param response
//	 * @throws Exception
//	 */
//	@GetMapping(value = "/download/**")
//	public void download(HttpServletRequest request, HttpServletResponse response) throws Exception {
//		// ISO-8859-1 ==> UTF-8 进行编码转换
//		String filePath = extractPathFromPattern(request);
//		// 其余处理略
//		InputStream inputStream = null;
//		OutputStream outputStream = null;
//		try {
//			filePath = filePath.replace("..", "");
//			if (filePath.endsWith(",")) {
//				filePath = filePath.substring(0, filePath.length() - 1);
//			}
//			String localPath = uploadpath;
//			String downloadFilePath = localPath + File.separator + filePath;
//			File file = new File(downloadFilePath);
//	         if (file.exists()) {
//	         	response.setContentType("application/force-download");// 设置强制下载不打开            
//	 			response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
//	 			inputStream = new BufferedInputStream(new FileInputStream(file));
//	 			outputStream = response.getOutputStream();
//	 			byte[] buf = new byte[1024];
//	 			int len;
//	 			while ((len = inputStream.read(buf)) > 0) {
//	 				outputStream.write(buf, 0, len);
//	 			}
//	 			response.flushBuffer();
//	         }
//
//		} catch (Exception e) {
//			log.info("文件下载失败" + e.getMessage());
//			// e.printStackTrace();
//		} finally {
//			if (inputStream != null) {
//				try {
//					inputStream.close();
//				} catch (IOException e) {
//					e.printStackTrace();
//				}
//			}
//			if (outputStream != null) {
//				try {
//					outputStream.close();
//				} catch (IOException e) {
//					e.printStackTrace();
//				}
//			}
//		}
//
//	}

    /**
     * @功能：pdf预览Iframe
     * @param modelAndView
     * @return
     */
    @RequestMapping("/pdf/pdfPreviewIframe")
    public ModelAndView pdfPreviewIframe(ModelAndView modelAndView) {
        modelAndView.setViewName("pdfPreviewIframe");
        return modelAndView;
    }

    /**
     * 读取本地pdf,这里设置的是预览
     */
    @ApiOperation(value="pdf预览", notes="pdf预览，参数pdfFileName：\\temp\\TCP-IP_1676365447720.pdf")
    @GetMapping("/pdf/pdfPreview")
    public void pdfPreview(@RequestParam(name="pdfFileName") String pdfFileName,
                            HttpServletRequest request, @NotNull HttpServletResponse response ) {
        response.reset();
        response.setContentType("application/pdf");
        try {
            File file = new File(uploadpath + File.separator + pdfFileName);
            FileInputStream fileInputStream = new FileInputStream(file);
            OutputStream outputStream = response.getOutputStream();
            IOUtils.write(IOUtils.toByteArray(fileInputStream), outputStream);
            response.setHeader("Content-Disposition",
                    "inline; filename= file");
            outputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *  把指定URL后的字符串全部截断当成参数
     *  这么做是为了防止URL中包含中文或者特殊字符（/等）时，匹配不了的问题
     * @param request
     * @return
     */
    private static String extractPathFromPattern(final HttpServletRequest request) {
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }

    /**
     * 如果不传provinceCode则查询的为所有省的列表数据，传则代表查当前省下对应的市区
     * @param provinceCode
     * @return
     */
    @ApiOperation(value="查询省市区信息", notes="查询省市区信息")
    @GetMapping("/getAreaList")
    public Result<?> getAreaList(@RequestParam(name="provinceCode", required = false) String provinceCode){
        if (null == provinceCode){
            String redisKey = "area:list:all";
            List<AreaProvince> provinceList = (List<AreaProvince>) redisUtil.get(redisKey);
            if (null == provinceList){
                provinceList = areaProvinceService.getAreaProvinces();
                redisUtil.set(redisKey,provinceList);
            }
            return Result.OK(provinceList);
        }
        String provinceKey = "area:list:" + provinceCode;
        List<AreaCity> cityList = (List<AreaCity>) redisUtil.get(provinceKey);
        if (null == cityList){
            cityList = areaProvinceService.getCityListByProvinceCode(provinceCode);
            redisUtil.set(provinceKey, cityList);
        }
        return Result.OK(cityList);
    }

}
